/**
 * 
 */
package org.simplextensions.scanner;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import javassist.bytecode.annotation.Annotation;

/**
 * 
 * @author Tomasz Krzyzak, <a
 *         href="mailto:tomasz.krzyzak@gmail.com">tomasz.krzyzak@gmail.com</a>
 * @since 31-08-2010 21:21:15
 */
public class ClasspathScanner2 {

	private final Map<String, List<IClassScanner>> scannersMap = new HashMap<String, List<IClassScanner>>();

	public ClasspathScanner2(List<IClassScanner> scanners) {
	}

	public void scannClassPath(IClasspathScannerBundle bundle, Set<String> classNames) throws ClasspathScannerException {
		Set<String> names= new HashSet<String>(classNames!=null?classNames:new LinkedList<String>());
		Iterator<ClassFile> iterator = bundle.classFileIterator(classNames);
		Collection<ClassFile> classFiles = new LinkedList<ClassFile>();
		
		while (iterator.hasNext()) {
			ClassFile next = iterator.next();
			names.remove(next.getName());
			classFiles.add(next);
		}
		if (names.size()==0){
			for (ClassFile cf : classFiles){
				scannClassFile(cf);
			}
		}
	}

	/**
	 * @param classFile
	 */
	private void scannClassFile(ClassFile classFile) {
		executeClassScanners(classFile, (AnnotationsAttribute) classFile.getAttribute(AnnotationsAttribute.invisibleTag));
		executeClassScanners(classFile,(AnnotationsAttribute) classFile.getAttribute(AnnotationsAttribute.visibleTag));
	}

	private void executeClassScanners(ClassFile classFile, AnnotationsAttribute attributeInfo) {
		if (attributeInfo == null)
			return;
		for (Annotation a : attributeInfo.getAnnotations()) {
			for (IClassScanner listener : scannersMap.get(a.getTypeName())) {
				listener.scanClass(classFile, a);
			}
		}
	}
}
